package com.ylw.entity;

import com.ylw.entity.request.RequestParameter;
import com.ylw.inter.ReadTable;
import com.ylw.util.Constant;
import com.ylw.util.enumClass.TableHeadParameterName.*;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.log4j.Logger;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;

import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.concurrent.Callable;

/**
 * 请求入参类
 * 基本逻辑
 * 1.判断该参数是否为map，如果是：之后所有的参数为map直到下一个map出现    出现嵌套map出错，可能需要缩进
 * 2.当出现中文表头时，更新表头，然后根据表头匹配数据，
 * 数据结构为   顶级参数名称为键，parameter对象为值
 * <p>
 * 基本匹配firstrequest文件
 */
public class Request implements Callable<String>, ReadTable {

    private static final Logger logger = Logger.getLogger(Request.class);

    protected Map<String, List<RequestParameter>> map = new HashMap();//结果集  这里类型不能为Parameter
    protected XWPFTable table;
    protected Service service;
    private int header = 0;//当前表头在表的哪一行

    public Request(Service service, XWPFTable table) {
        this.table = table;
        this.service = service;
    }


    /**
     * 当碰到map类型的对象时，把nextParameterInMap为真,并更新parameters为该map对象键所对应的List<parameter>
     * 当碰到header对象时，更新header值
     *
     * @return
     */
    @Override
    public String read() {
        if (table == null) {
            return Constant.NULL;
        }
        boolean nextParameterInMap = false;
        ArrayList<RequestParameter> parameters = null;
        for (int i = 0; i < table.getNumberOfRows(); i++) {
            XWPFTableRow row = table.getRow(i);
            RequestParameter parameter = new RequestParameter();
            parameter.setOrder(i);
            if (isMapType(row, 0, parameter)) {
                nextParameterInMap = true;
                parameters = new ArrayList();
                map.put(parameter.getName(), parameters);
            }
            else if (isTableHeader(row, 0, parameter)) {
                header = i;
                continue;
            }
            //反射生成对象
            Map map = new HashMap();
            for (int j = 0; j < row.getTableCells().size(); j++) {
                String input = table.getRow(header).getCell(j).getText().trim();
                String key = getKeyByHeadCol(input);
                String value = row.getCell(j).getText().trim();
                if(key !=null && key.equals("allowNull")){
                    boolean isAllowNull = ParameterAllowNull.getAbs(input,value);
                    map.put(key,isAllowNull);
                    continue;
                }
                map.put(key, value);
            }
            try {
                BeanUtils.populate(parameter, map);
            }
            catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            catch (InvocationTargetException e) {
                e.printStackTrace();
            }
            logger.info(parameter);
            if (nextParameterInMap) {
                parameters.add(parameter);
            }
            else {
                this.map.put(parameter.getName(), Collections.singletonList(parameter));
            }
        }
        return Constant.FINISHED;
    }

    @Override
    public String call() throws Exception {
        return read();
    }

    /**
     * 查看该列是否是map类型的对象
     * <p>
     *
     * @param row
     * @return
     */
    private boolean isMapType(XWPFTableRow row, int col, Parameter parameter) {
        XWPFTableCell cell = row.getCell(col);
        if (cell == null) {
            return false;
        }

        //当格式为一列为一个属性时 且开头为Map
        if (row.getTableCells().size() == 1) {
            String value = cell.getText().trim();
            if (value.toUpperCase().startsWith("MAP")) {
                String[] vs = value.split(">");
                parameter.setName(vs[1].trim());
                return true;
            }
        }

        //当只有两列 且第二列为map时
        if (row.getTableCells().size() == 2) {
            cell = row.getCell(col+1);
            String value = cell.getText().trim();
            if (value.toUpperCase().startsWith("MAP")) {
                return true;
            }
        }

        return false;
    }


    /**
     * 判断是否为表头
     * 依据第一列的中文字符判断
     *
     * @param row
     * @return
     */
    private boolean isTableHeader(XWPFTableRow row, int col, Parameter parameter) {
        XWPFTableCell cell = row.getCell(col);
        if (cell == null) {
            return false;
        }
        if (ParameterName.getParamterName(cell.getText().trim()) != null) {
            return true;
        }
        return false;
    }

    /**
     * 通过表头列名称 获取该列对应 parameter里面的属性
     *
     * @param headColName
     * @return
     */
    public String getKeyByHeadCol(String headColName) {
        String result;
        if ((result = ParameterName.getParamterName(headColName)) != null || (result = ParameterType.getParamterName(headColName)) != null || (result = ParameterAllowNull.getParamterName(headColName)) != null || (result = ParameterRemark.getParamterName(headColName)) != null) {
            return result;
        }
        return result;
    }

    public Map<String, List<RequestParameter>> getMap() {
        return map;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("{");
        sb.append("\"map\":").append(map);
        sb.append(",\"table\":").append(table);
        sb.append(",\"service\":").append(service);
        sb.append(",\"header\":").append(header);
        sb.append('}');
        return sb.toString();
    }
}
